﻿#include "CameraDataReadThread.h"

bool CameraDataReadThread::isRun = true;

CameraDataReadThread::CameraDataReadThread(Buffer *Pbuffer)
{
    m_Buffer     = Pbuffer;
    // CCyUSBDevice构造参数1: 用于传递当pnp事件发生时的回调函数（重载); 参数2: 用于表示当前 CyUsb.inf 文件的 [Strings] 部分中定义的 GUID，否则使用默认guid
    m_UsbDevice  = new CCyUSBDevice;
    // 缓冲区大小为一行数据的3倍
    m_PBufferData = new uint8_t[ImageDefaultWidth * ImageDefaultPixel * 3];
    m_PDataHead = m_PDataTail = m_PBufferData;
    m_ReadInAddress = -1;
    m_CurrentDevice = nullptr;
}

bool CameraDataReadThread::DataSave(uint8_t *PData, size_t len)
{
    m_Cols = ImageDefaultWidth * ImageDefaultPixel;
    // 此处采取循环队列
    for (size_t i = 0; i < len; i++)
    {
        m_PDataTail[(i + 1) % m_Cols * 3] = *(PData + i);
    }
    m_DataSize += len;
    if (m_DataSize >= m_Cols)
    {
        // 此时攒满一行图片数据
        uint8_t* array = m_PDataHead;
        m_Buffer->write(array, m_Cols, num);
        m_PDataHead = m_PBufferData + (m_PDataHead - m_PBufferData + m_Cols) % (ImageDefaultWidth * ImageDefaultPixel * 3);
        m_DataSize -= m_Cols;
        ++num %= ImageDefaultHeight + 1;
    }

    return true;
}

void CameraDataReadThread::run()
{
    // 读取数据(这里是在子线程中执行，但是Open必须与最初new的对象以及注册线程在同一线程，所以在主线程提前打开，该run方法只负责读取数据)
    // 如果上层关闭读取，会将m_IsRun关闭，此时当前子线程就会进入wait等待上层调用wake唤醒.
    while(1)
    {
        QMutexLocker locker(&m_Mutex);
        m_Wait.wait(&m_Mutex);
         this->Read();
    }
    // 开启事件循环
    this->exec();
}

bool CameraDataReadThread::InAddress(ParameterKind Kind, uint8_t* data)
{
    if(data == nullptr) return false;
    switch(Kind)
    {
    case ParameterKind::Get:
        *data = m_ReadInAddress;
        break;
    case ParameterKind::Set:
        if(*data <= 0) return false;
        m_ReadInAddress = *data;
        break;
    }
    return true;
}

void CameraDataReadThread::Read()
{
    std::shared_ptr<byte> recivce_Buffer(new byte[ImageDefaultWidth]);

    LONG recieveLen = ImageDefaultWidth;

    qDebug() << "设备" << m_CurrentOpen << "打开成功" << "输入端地址为: " << m_ReadInAddress;
    CCyUSBEndPoint *recieve_Endpt = m_CurrentDevice->EndPointOf(m_ReadInAddress);         // 指定端点，使能传输
    while (1)
    {
        recieveLen = 1024;  // 不清楚为什么一次只能读取1024字节
        if (recieve_Endpt->XferData(recivce_Buffer.get(), recieveLen))
        {
            // 这里按照组成逻辑得先将数据再处理，而不是直接发送给下一层。
            this->DataSave(recivce_Buffer.get(), recieveLen);
        }
        else {
            qDebug() << "获取数据失败";
            return ;
        }
        if(isRun == false) break;
    }
}

bool CameraDataReadThread::CurrentOpen(ParameterKind Kind, int *i, uint8_t *inAddress)
{
    if(i == nullptr || inAddress == nullptr) return false;
    switch(Kind)
    {
    case ParameterKind::Get:
        *i = m_CurrentOpen;
        *inAddress = m_ReadInAddress;
        break;
    case ParameterKind::Set:
        if(*i < 0) return false;
        if(*inAddress <= 0) return false;
        m_CurrentOpen = *i;
        m_ReadInAddress = *inAddress;
        // 设置完当前打开视频后就从这个索引处读取数据
        CameraDataReadThread::isRun = true;
        if(m_CurrentDevice == nullptr)  m_CurrentDevice = new CCyUSBDevice;
        QMutexLocker locker(&m_Mutex);
        try {
        if(!m_CurrentDevice->Open(m_CurrentOpen))
        {
            qDebug() << QString("第%1个设备打开失败!").arg(m_CurrentOpen);
            return false;
        }else qDebug() << "设备打开成功";
    } catch (const char* e) {
        qDebug() << "捕获异常为: " << e;
    }
        m_Wait.wakeAll();
        break;
    }

    return true;
}

bool CameraDataReadThread::CloseCurrentDevice()
{
    // if(CameraDataReadThread::isRun == false) return false;
    CameraDataReadThread::isRun = false;
    if(m_CurrentDevice != nullptr)
    {
        try {
                // delete m_CurrentDevice;      (不用delete因为在设备拔出时会自动调用Close并且会自动delete)
                m_CurrentDevice = nullptr;
        } catch (const char* e) {
            qDebug() << "CameraDataReadThread::CloseCurrentDevice捕获异常: " << e;
        }
    }

    return true;
}



